最近对HBase做了升级,从0.92升级到了1.2.0-cdh5.11.1,版本跨度很大,而且从社区版转向了Cloudera。之所以改用CDH,是因为大概两年前在前一个公司做HBase CDH4到CDH5的升级,由于一开始搭建集群的时候就没用Cloudera Manager,所以导致升级非常痛苦,因为两个版本之间底层文件的格式变了,所以为了稳定,找了另外一批机器装了CDH5,然后实现源数据的双写,再用export+import把CDH4的数据全量导过去,最后稳定并行一段时间之后把CDH4停掉。整个流程听着就很麻烦,开销也很大(相当于资源*2),所以这次选择了先把0.92平移到CDH4,然后用Cloudera Manager升级,整个过程非常平滑
升级之后(准确说是升级之前就需要准备)发现HBase client的API已经有了很大的变动,所以也花了一些时间来研究,以下是一些心得
有些旧的类和函数已经被废弃或将要被废弃,尽量使用新的API,比如:
- 使用ConnectionFactory管理Connection
- 用Table替代HTable,用Connection替代HConnection,Admin替代HBaseAdmin等等
- 使用工厂类而不是原生的构造函数来生成类
- 获取table改用参数TableName,而不是之前的String或者byte[]
Table的使用
以前的使用方式1
2
3
4Configuration conf = HBaseConfiguration.create();
HTable t = new HTable(conf, "mytable");
t.put(new Put(row).add(fam, qual, value));
t.close();
现在的使用方式1
2
3
4
5
6Configuration conf = HBaseConfiguration.create();
Connection conn = ConnectionFactory.createConnection(conf)
Table t = conn.getTable(TableName.valueOf("mytable"));
t.put(new Put(row).add(fam, qual, value));
t.close();
conn.close;
无论是Connection, Table, Admin还是Scanner,用完就关,由于这些接口或多或少的都在client端或server端(Scanner)hold住了一些资源,所以对于性能来讲,及时关掉是非常必要的。另外,由于这些接口都继承了Closeable,所以使用Java的try语法能否非常容易的close掉,而在之前的版本需要在try之外声明,然后在finally中关闭,还要加上null check
1
2
3
4
5try (Connection connection = ConnectionFactory.createConnection(conf);
Admin admin = connection.getAdmin();
Table table = connection.getTable(tableName);) {
table.get(new Get(...))
}Connection是线程安全且非常重的对象,因为它包含了zookeeper的连接,socket连接等等,所以最好在一个应用中只创建一个Connection供多线程使用,并且在整个程序退出之前才关闭。与Connection相反,Table,Admin等都是相对比较轻量的组件,并且
非
线程安全,所以可以针对每个请求创建一个单独的实例,请求处理完就关闭使用BufferedMutator实现批量/流式Puts,它替代了之前版本的手动flush,提供了高性能的流式写入